/*      */ package com.zimbra.cs.mailbox;
/*      */ 
/*      */ import com.google.common.base.Objects;
/*      */ import com.google.common.base.Objects.ToStringHelper;
/*      */ import com.google.common.base.Strings;
/*      */ import com.zimbra.common.account.Key.AccountBy;
/*      */ import com.zimbra.common.account.ZAttrProvisioning.PrefCalendarApptVisibility;
/*      */ import com.zimbra.common.calendar.ICalTimeZone;
/*      */ import com.zimbra.common.calendar.ParsedDateTime;
/*      */ import com.zimbra.common.calendar.ZCalendar.ICalTok;
/*      */ import com.zimbra.common.calendar.ZCalendar.ZProperty;
/*      */ import com.zimbra.common.calendar.ZCalendar.ZVCalendar;
/*      */ import com.zimbra.common.localconfig.DebugConfig;
/*      */ import com.zimbra.common.mailbox.Color;
/*      */ import com.zimbra.common.mime.InternetAddress;
/*      */ import com.zimbra.common.service.ServiceException;
/*      */ import com.zimbra.common.util.Log;
/*      */ import com.zimbra.common.util.LogFactory;
/*      */ import com.zimbra.common.util.StringUtil;
/*      */ import com.zimbra.common.util.ZimbraLog;
/*      */ import com.zimbra.common.zmime.ZMimeMessage;
/*      */ import com.zimbra.cs.account.AccessManager;
/*      */ import com.zimbra.cs.account.Account;
/*      */ import com.zimbra.cs.account.CalendarResource;
/*      */ import com.zimbra.cs.account.Provisioning;
/*      */ import com.zimbra.cs.account.accesscontrol.Rights.User;
/*      */ import com.zimbra.cs.db.DbMailItem;
/*      */ import com.zimbra.cs.index.IndexDocument;
/*      */ import com.zimbra.cs.index.SortBy;
/*      */ import com.zimbra.cs.mailbox.calendar.CalendarMailSender;
/*      */ import com.zimbra.cs.mailbox.calendar.Invite;
/*      */ import com.zimbra.cs.mailbox.calendar.InviteChanges;
/*      */ import com.zimbra.cs.mailbox.calendar.RecurId;
/*      */ import com.zimbra.cs.mailbox.calendar.Util;
/*      */ import com.zimbra.cs.mailbox.calendar.ZAttendee;
/*      */ import com.zimbra.cs.mailbox.calendar.ZOrganizer;
/*      */ import com.zimbra.cs.mime.Mime.FixedMimeMessage;
/*      */ import com.zimbra.cs.mime.ParsedAddress;
/*      */ import com.zimbra.cs.mime.ParsedMessage;
/*      */ import com.zimbra.cs.mime.ParsedMessageOptions;
/*      */ import com.zimbra.cs.redolog.RedoLogManager;
/*      */ import com.zimbra.cs.redolog.RedoLogProvider;
/*      */ import com.zimbra.cs.redolog.op.CreateCalendarItemPlayer;
/*      */ import com.zimbra.cs.redolog.op.RedoableOp;
/*      */ import com.zimbra.cs.service.util.ItemId;
/*      */ import com.zimbra.cs.store.MailboxBlob;
/*      */ import com.zimbra.cs.store.StagedBlob;
/*      */ import com.zimbra.cs.util.AccountUtil;
/*      */ import com.zimbra.cs.util.AccountUtil.AccountAddressMatcher;
/*      */ import com.zimbra.soap.mail.type.CalendarItemInfo;
/*      */ import java.io.IOException;
/*      */ import java.util.ArrayList;
/*      */ import java.util.Collections;
/*      */ import java.util.HashSet;
/*      */ import java.util.Iterator;
/*      */ import java.util.List;
/*      */ import java.util.Set;
/*      */ import javax.mail.MessagingException;
/*      */ import javax.mail.internet.MimeMessage;
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ public class Message
/*      */   extends MailItem
/*      */ {
/*      */   static class DraftInfo
/*      */   {
/*      */     String accountId;
/*      */     String identityId;
/*      */     String replyType;
/*      */     String origId;
/*      */     long autoSendTime;
/*      */     
/*      */     private DraftInfo() {}
/*      */     
/*      */     public DraftInfo(String rt, String id, String ident, String account, long autoSendTime)
/*      */     {
/*  101 */       this.replyType = rt;
/*  102 */       this.origId = id;
/*  103 */       this.identityId = ident;
/*  104 */       this.accountId = account;
/*  105 */       this.autoSendTime = autoSendTime;
/*      */     }
/*      */     
/*      */     public DraftInfo(Metadata meta) throws ServiceException {
/*  109 */       this.accountId = meta.get("aid", null);
/*  110 */       this.identityId = meta.get("idnt", null);
/*  111 */       this.replyType = meta.get("dt", null);
/*  112 */       this.origId = meta.get("do", null);
/*  113 */       this.autoSendTime = meta.getLong("ast", 0L);
/*      */     }
/*      */     
/*      */     public boolean equals(Object obj)
/*      */     {
/*  118 */       if ((obj != null) && ((obj instanceof DraftInfo))) {
/*  119 */         DraftInfo dInfo = (DraftInfo)obj;
/*  120 */         return (StringUtil.equal(this.accountId, dInfo.accountId)) && (StringUtil.equal(this.identityId, dInfo.identityId)) && (StringUtil.equal(this.replyType, dInfo.replyType)) && (StringUtil.equal(this.origId, dInfo.origId)) && (this.autoSendTime == dInfo.autoSendTime);
/*      */       }
/*      */       
/*      */ 
/*      */ 
/*      */ 
/*  126 */       return false;
/*      */     } }
/*      */   
/*      */   public static class CalendarItemInfo { public static final int CALITEM_ID_NONE = 0;
/*      */     private final int mCalendarItemId;
/*      */     private final int mComponentNo;
/*      */     private final Invite mInvite;
/*      */     private final InviteChanges mInviteChanges;
/*      */     private final String calOwner;
/*      */     private static final String FN_CALITEMID = "a";
/*      */     private static final String FN_COMPNO = "c";
/*      */     private static final String FN_INV = "inv";
/*      */     private static final String FN_INV_CHANGES = "invChg";
/*      */     private static final String FN_CAL_OWNER = "calOwner";
/*      */     
/*  141 */     CalendarItemInfo(int calItemId, String owner, int componentNo, Invite inv, InviteChanges changes) { this.mCalendarItemId = calItemId;
/*  142 */       this.mComponentNo = componentNo;
/*  143 */       this.mInvite = inv;
/*  144 */       this.mInviteChanges = changes;
/*  145 */       this.calOwner = owner;
/*      */     }
/*      */     
/*      */     CalendarItemInfo(int calItemId, int componentNo, Invite inv, InviteChanges changes) {
/*  149 */       this(calItemId, null, componentNo, inv, changes);
/*      */     }
/*      */     
/*  152 */     public String getCalOwner() { return this.calOwner; }
/*      */     
/*      */ 
/*      */ 
/*      */     public ItemId getCalendarItemId()
/*      */     {
/*  158 */       if (!calItemCreated()) {
/*  159 */         return null;
/*      */       }
/*  161 */       return new ItemId(this.calOwner, this.mCalendarItemId);
/*      */     }
/*      */     
/*  164 */     public int getComponentNo() { return this.mComponentNo; }
/*  165 */     public Invite getInvite() { return this.mInvite; }
/*  166 */     public InviteChanges getInviteChanges() { return this.mInviteChanges; }
/*  167 */     public boolean calItemCreated() { return this.mCalendarItemId != 0; }
/*      */     
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */     Metadata encodeMetadata()
/*      */     {
/*  176 */       Metadata meta = new Metadata();
/*  177 */       meta.put("a", this.mCalendarItemId);
/*  178 */       meta.put("c", this.mComponentNo);
/*  179 */       if ((this.mInviteChanges != null) && (!this.mInviteChanges.noChange()))
/*  180 */         meta.put("invChg", this.mInviteChanges.toString());
/*  181 */       if (this.mInvite != null)
/*  182 */         meta.put("inv", Invite.encodeMetadata(this.mInvite));
/*  183 */       if (this.calOwner != null)
/*  184 */         meta.put("calOwner", this.calOwner);
/*  185 */       return meta;
/*      */     }
/*      */     
/*      */     static CalendarItemInfo decodeMetadata(Metadata meta, Mailbox mbox) throws ServiceException {
/*  189 */       int calItemId = (int)meta.getLong("a", 0L);
/*  190 */       int componentNo = (int)meta.getLong("c");
/*  191 */       String changes = meta.get("invChg", null);
/*  192 */       String owner = meta.get("calOwner", null);
/*  193 */       InviteChanges invChanges = changes != null ? new InviteChanges(changes) : null;
/*  194 */       Invite inv = null;
/*  195 */       Metadata metaInv = meta.getMap("inv", true);
/*  196 */       if (metaInv != null) {
/*  197 */         int mboxId = mbox.getId();
/*  198 */         ICalTimeZone accountTZ = Util.getAccountTimeZone(mbox.getAccount());
/*  199 */         inv = Invite.decodeMetadata(mboxId, metaInv, null, accountTZ);
/*      */       }
/*  201 */       return new CalendarItemInfo(calItemId, owner, componentNo, inv, invChanges);
/*      */     }
/*      */   }
/*      */   
/*  205 */   private static final Log LOG = LogFactory.getLog(Message.class);
/*      */   private String sender;
/*      */   private String recipients;
/*      */   private String fragment;
/*      */   private String rawSubject;
/*      */   private DraftInfo draftInfo;
/*      */   private ArrayList<CalendarItemInfo> calendarItemInfos;
/*      */   private String calendarIntendedFor;
/*      */   
/*      */   Message(Mailbox mbox, MailItem.UnderlyingData ud)
/*      */     throws ServiceException
/*      */   {
/*  217 */     this(mbox, ud, false);
/*      */   }
/*      */   
/*      */ 
/*      */   Message(Mailbox mbox, MailItem.UnderlyingData ud, boolean skipCache)
/*      */     throws ServiceException
/*      */   {
/*  224 */     super(mbox, ud, skipCache);
/*  225 */     if ((this.mData.type != MailItem.Type.MESSAGE.toByte()) && (this.mData.type != MailItem.Type.CHAT.toByte())) {
/*  226 */       throw new IllegalArgumentException();
/*      */     }
/*  228 */     if (this.mData.parentId < 0) {
/*  229 */       this.mData.parentId = (-this.mId);
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public boolean isDraft()
/*      */   {
/*  237 */     return isTagged(Flag.FlagInfo.DRAFT);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public String getRecipients()
/*      */   {
/*  244 */     return Strings.nullToEmpty(this.recipients);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public String getFragment()
/*      */   {
/*  253 */     return Strings.nullToEmpty(this.fragment);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   String getNormalizedSubject()
/*      */   {
/*  263 */     return super.getSubject();
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public String getSubject()
/*      */   {
/*  270 */     return Strings.nullToEmpty(this.rawSubject);
/*      */   }
/*      */   
/*      */ 
/*      */   public String getSender()
/*      */   {
/*  276 */     return Strings.nullToEmpty(this.sender);
/*      */   }
/*      */   
/*      */   public String getSortSubject()
/*      */   {
/*  281 */     return getNormalizedSubject();
/*      */   }
/*      */   
/*      */   public String getSortSender()
/*      */   {
/*  286 */     String sender = new ParsedAddress(getSender()).getSortString();
/*      */     
/*  288 */     return DbMailItem.normalize(sender, 128);
/*      */   }
/*      */   
/*      */   public String getSortRecipients()
/*      */   {
/*  293 */     List<InternetAddress> iaddrs = InternetAddress.parseHeader(getRecipients());
/*  294 */     if ((iaddrs == null) || (iaddrs.isEmpty())) {
/*  295 */       return null;
/*      */     }
/*  297 */     List<ParsedAddress> paddrs = new ArrayList(iaddrs.size());
/*  298 */     for (InternetAddress iaddr : iaddrs) {
/*  299 */       paddrs.add(new ParsedAddress(iaddr));
/*      */     }
/*  301 */     return DbMailItem.normalize(ParsedAddress.getSortString(paddrs), 128);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public boolean isFromMe()
/*      */   {
/*  308 */     return this.mData.isSet(Flag.FlagInfo.FROM_ME);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   public int getConversationId()
/*      */   {
/*  315 */     return this.mData.parentId;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public String getDraftOrigId()
/*      */   {
/*  324 */     return (this.draftInfo == null) || (this.draftInfo.origId == null) ? "" : this.draftInfo.origId;
/*      */   }
/*      */   
/*      */   void setDraftOrigId(String origId) {
/*  328 */     if (this.draftInfo == null) {
/*  329 */       this.draftInfo = new DraftInfo(null);
/*      */     }
/*  331 */     this.draftInfo.origId = origId;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public String getDraftReplyType()
/*      */   {
/*  344 */     return (this.draftInfo == null) || (this.draftInfo.replyType == null) ? "" : this.draftInfo.replyType;
/*      */   }
/*      */   
/*      */   void setDraftReplyType(String replyType) {
/*  348 */     if (this.draftInfo == null) {
/*  349 */       this.draftInfo = new DraftInfo(null);
/*      */     }
/*  351 */     this.draftInfo.replyType = replyType;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public String getDraftAccountId()
/*      */   {
/*  362 */     return (this.draftInfo == null) || (this.draftInfo.accountId == null) ? "" : this.draftInfo.accountId;
/*      */   }
/*      */   
/*      */   void setDraftAccountId(String accountId) {
/*  366 */     if (this.draftInfo == null) {
/*  367 */       this.draftInfo = new DraftInfo(null);
/*      */     }
/*  369 */     this.draftInfo.accountId = accountId;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public String getDraftIdentityId()
/*      */   {
/*  380 */     return (this.draftInfo == null) || (this.draftInfo.identityId == null) ? "" : this.draftInfo.identityId;
/*      */   }
/*      */   
/*      */   void setDraftIdentityId(String identityId) {
/*  384 */     if (this.draftInfo == null) {
/*  385 */       this.draftInfo = new DraftInfo(null);
/*      */     }
/*  387 */     this.draftInfo.identityId = identityId;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public long getDraftAutoSendTime()
/*      */   {
/*  396 */     return this.draftInfo == null ? 0L : this.draftInfo.autoSendTime;
/*      */   }
/*      */   
/*      */   public void setDraftAutoSendTime(long autoSendTime) throws ServiceException {
/*  400 */     if ((this.draftInfo == null) && (autoSendTime != 0L)) {
/*  401 */       this.draftInfo = new DraftInfo(null, null, null, null, autoSendTime);
/*  402 */       saveMetadata();
/*  403 */     } else if ((this.draftInfo != null) && (this.draftInfo.autoSendTime != autoSendTime)) {
/*  404 */       this.draftInfo.autoSendTime = autoSendTime;
/*  405 */       saveMetadata();
/*      */     }
/*      */   }
/*      */   
/*      */   public boolean isInvite()
/*      */   {
/*  411 */     return this.mData.isSet(Flag.FlagInfo.INVITE);
/*      */   }
/*      */   
/*      */   public boolean hasCalendarItemInfos() {
/*  415 */     return (this.calendarItemInfos != null) && (!this.calendarItemInfos.isEmpty());
/*      */   }
/*      */   
/*      */   public Iterator<CalendarItemInfo> getCalendarItemInfoIterator() {
/*  419 */     if (this.calendarItemInfos != null) {
/*  420 */       return this.calendarItemInfos.iterator();
/*      */     }
/*  422 */     return Collections.emptyList().iterator();
/*      */   }
/*      */   
/*      */   public CalendarItemInfo getCalendarItemInfo(int componentId)
/*      */   {
/*  427 */     if ((this.calendarItemInfos != null) && ((componentId < 0) || (componentId < this.calendarItemInfos.size()))) {
/*  428 */       return (CalendarItemInfo)this.calendarItemInfos.get(componentId);
/*      */     }
/*  430 */     return null;
/*      */   }
/*      */   
/*      */   public String getCalendarIntendedFor()
/*      */   {
/*  435 */     return this.calendarIntendedFor;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public MimeMessage getMimeMessage()
/*      */     throws ServiceException
/*      */   {
/*  453 */     return getMimeMessage(true);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   public MimeMessage getMimeMessage(boolean runConverters)
/*      */     throws ServiceException
/*      */   {
/*  472 */     MimeMessage mm = MessageCache.getMimeMessage(this, runConverters);
/*  473 */     if (((mm instanceof ZMimeMessage)) && (ZMimeMessage.usingZimbraParser())) {
/*      */       try {
/*  475 */         mm = new Mime.FixedMimeMessage(mm, this.mMailbox.getAccount());
/*      */       } catch (MessagingException e) {
/*  477 */         ZimbraLog.mailbox.info("could not copy MimeMessage; using original", e);
/*      */       }
/*      */     }
/*  480 */     return mm;
/*      */   }
/*      */   
/*      */   boolean isTaggable()
/*      */   {
/*  485 */     return true;
/*      */   }
/*      */   
/*      */   boolean isCopyable()
/*      */   {
/*  490 */     return true;
/*      */   }
/*      */   
/*      */   boolean isMovable()
/*      */   {
/*  495 */     return true;
/*      */   }
/*      */   
/*      */   boolean isMutable()
/*      */   {
/*  500 */     return isTagged(Flag.FlagInfo.DRAFT);
/*      */   }
/*      */   
/*      */   boolean canHaveChildren()
/*      */   {
/*  505 */     return false;
/*      */   }
/*      */   
/*      */   boolean canParent(MailItem item)
/*      */   {
/*  510 */     return false;
/*      */   }
/*      */   
/*      */   static class MessageCreateFactory {
/*      */     Message create(Mailbox mbox, MailItem.UnderlyingData data) throws ServiceException {
/*  515 */       return new Message(mbox, data);
/*      */     }
/*      */     
/*      */     MailItem.Type getType() {
/*  519 */       return MailItem.Type.MESSAGE;
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */   static Message create(int id, Folder folder, Conversation conv, ParsedMessage pm, StagedBlob staged, boolean unread, int flags, Tag.NormalizedTags ntags, DraftInfo dinfo, boolean noICal, ZCalendar.ZVCalendar cal, MailItem.CustomMetadata.CustomMetadataList extended)
/*      */     throws ServiceException
/*      */   {
/*  527 */     return createInternal(id, folder, conv, pm, staged, unread, flags, ntags, dinfo, noICal, cal, extended, new MessageCreateFactory());
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   static Message createInternal(int id, Folder folder, Conversation conv, ParsedMessage pm, StagedBlob staged, boolean unread, int flags, Tag.NormalizedTags ntags, DraftInfo dinfo, boolean noICal, ZCalendar.ZVCalendar cal, MailItem.CustomMetadata.CustomMetadataList extended, MessageCreateFactory fact)
/*      */     throws ServiceException
/*      */   {
/*  535 */     if ((folder == null) || (!folder.canContain(MailItem.Type.MESSAGE))) {
/*  536 */       throw MailServiceException.CANNOT_CONTAIN(folder, MailItem.Type.MESSAGE);
/*      */     }
/*  538 */     if (!folder.canAccess((short)4)) {
/*  539 */       throw ServiceException.PERM_DENIED("you do not have the required rights on the folder");
/*      */     }
/*  541 */     Mailbox mbox = folder.getMailbox();
/*  542 */     Account acct = mbox.getAccount();
/*      */     
/*  544 */     String sender = pm.getSenderEmail();
/*      */     
/*  546 */     List<Invite> components = null;
/*  547 */     String methodStr = null;
/*      */     
/*  549 */     if ((cal != null) && (folder.getId() != 4) && (folder.getId() != 3))
/*      */     {
/*      */ 
/*  552 */       boolean sentByMe = false;
/*  553 */       if (!Strings.isNullOrEmpty(sender)) {
/*  554 */         sentByMe = AccountUtil.addressMatchesAccountOrSendAs(acct, sender);
/*      */       }
/*      */       try {
/*  557 */         components = Invite.createFromCalendar(acct, pm.getFragment(acct.getLocale()), cal, sentByMe, mbox, id);
/*  558 */         methodStr = cal.getPropVal(ZCalendar.ICalTok.METHOD, ZCalendar.ICalTok.PUBLISH.toString()).toUpperCase();
/*  559 */         if (components != null) {
/*  560 */           flags |= Flag.BITMASK_INVITE;
/*  561 */           if ((ZCalendar.ICalTok.PUBLISH.toString().equals(methodStr)) && (!acct.getBooleanAttr("zimbraPrefCalendarAllowPublishMethodInvite", false)))
/*      */           {
/*      */ 
/*      */ 
/*  565 */             flags |= Flag.BITMASK_ATTACHED;
/*  566 */             components = null;
/*      */           }
/*      */         }
/*      */       } catch (Exception e) {
/*  570 */         ZimbraLog.calendar.warn("Unable to process iCalendar attachment", e);
/*      */       }
/*      */     }
/*      */     
/*      */ 
/*  575 */     long date = pm.getReceivedDate();long now = System.currentTimeMillis();
/*  576 */     if ((date < 0L) || (date > now)) {
/*  577 */       date = now;
/*      */     }
/*  579 */     MailItem.UnderlyingData data = new MailItem.UnderlyingData();
/*  580 */     data.id = id;
/*  581 */     data.type = fact.getType().toByte();
/*  582 */     if (conv != null) {
/*  583 */       data.parentId = conv.getId();
/*      */     }
/*  585 */     data.folderId = folder.getId();
/*  586 */     data.indexId = ((!folder.inSpam()) || (acct.isJunkMessagesIndexingEnabled()) ? MailItem.IndexStatus.DEFERRED.id() : MailItem.IndexStatus.DONE.id());
/*  587 */     data.locator = staged.getLocator();
/*  588 */     data.imapId = id;
/*  589 */     data.date = ((int)(date / 1000L));
/*  590 */     data.size = staged.getSize();
/*  591 */     data.setBlobDigest(staged.getDigest());
/*  592 */     data.setFlags(flags & (Flag.FLAGS_MESSAGE | Flag.FLAGS_GENERIC));
/*  593 */     data.setTags(ntags);
/*  594 */     data.setSubject(pm.getNormalizedSubject());
/*  595 */     data.metadata = encodeMetadata(DEFAULT_COLOR_RGB, 1, 1, extended, pm, pm.getFragment(acct.getLocale()), dinfo, null, null).toString();
/*  596 */     data.unreadCount = (unread ? 1 : 0);
/*  597 */     data.contentChanged(mbox);
/*      */     
/*  599 */     ZimbraLog.mailop.info("Adding Message: id=%d, Message-ID=%s, parentId=%d, folderId=%d, folderName=%s.", new Object[] { Integer.valueOf(data.id), pm.getMessageID(), Integer.valueOf(data.parentId), Integer.valueOf(folder.getId()), folder.getName() });
/*      */     
/*  601 */     new DbMailItem(mbox).setSender(pm.getParsedSender().getSortString()).setRecipients(ParsedAddress.getSortString(pm.getParsedRecipients())).create(data);
/*      */     
/*      */ 
/*      */ 
/*  605 */     Message msg = fact.create(mbox, data);
/*      */     
/*      */ 
/*  608 */     if (components != null) {
/*      */       try {
/*  610 */         msg.processInvitesAfterCreate(methodStr, folder.getId(), !noICal, pm, components);
/*      */       } catch (Exception e) {
/*  612 */         ZimbraLog.calendar.warn("Unable to process iCalendar attachment", e);
/*      */       }
/*      */     }
/*      */     
/*  616 */     msg.finishCreation(conv);
/*  617 */     return msg;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   private boolean manageCalendar(String ownerEmail)
/*      */     throws ServiceException
/*      */   {
/*  625 */     if (Strings.isNullOrEmpty(ownerEmail)) {
/*  626 */       return false;
/*      */     }
/*  628 */     Account ownerAcct = Provisioning.getInstance().get(Key.AccountBy.name, ownerEmail);
/*  629 */     if (ownerAcct == null) {
/*  630 */       ZimbraLog.account.info("Account = %s not present.", new Object[] { ownerEmail });
/*  631 */       return false;
/*      */     }
/*  633 */     AccountUtil.AccountAddressMatcher acctMatcher = new AccountUtil.AccountAddressMatcher(ownerAcct);
/*  634 */     for (Mountpoint sharedCal : getMailbox().getCalendarMountpoints(getMailbox().getOperationContext(), SortBy.NONE)) {
/*  635 */       if (sharedCal.canAccess((short)16)) {
/*  636 */         String calOwner = Provisioning.getInstance().get(Key.AccountBy.id, sharedCal.getOwnerId()).getName();
/*  637 */         if (acctMatcher.matches(calOwner)) {
/*  638 */           return true;
/*      */         }
/*      */       }
/*      */     }
/*  642 */     return false;
/*      */   }
/*      */   
/*      */ 
/*      */   private static String getCalendarIntendedFor(MimeMessage msg)
/*      */   {
/*      */     String headerVal;
/*      */     try
/*      */     {
/*  651 */       headerVal = msg.getHeader("X-Zimbra-Calendar-Intended-For", null);
/*      */     } catch (MessagingException e) {
/*  653 */       ZimbraLog.calendar.warn("ignoring error while checking for %s header on incoming message", "X-Zimbra-Calendar-Intended-For", e);
/*      */       
/*  655 */       return null;
/*      */     }
/*  657 */     if ((headerVal == null) || (headerVal.length() == 0)) {
/*  658 */       return null;
/*      */     }
/*  660 */     return headerVal;
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */   public CalendarItemInfo getRemoteCalendarItem(Invite invite)
/*      */   {
/*  668 */     CalendarItemInfo remoteCalendarItem = null;
/*      */     try
/*      */     {
/*  671 */       String headerVal = getCalendarIntendedFor(getMimeMessage());
/*  672 */       if ((headerVal != null) && (headerVal.length() > 0)) {
/*  673 */         AccountUtil.AccountAddressMatcher acctMatcher = new AccountUtil.AccountAddressMatcher(this.mMailbox.getAccount());
/*  674 */         if ((!acctMatcher.matches(headerVal)) && (manageCalendar(headerVal))) {
/*  675 */           Provisioning prov = Provisioning.getInstance();
/*  676 */           Account ownerAcct = prov.get(Key.AccountBy.name, headerVal);
/*  677 */           remoteCalendarItem = this.mMailbox.getRemoteCalItemByUID(ownerAcct, invite.getUid(), true, false);
/*      */         }
/*      */       }
/*      */     } catch (ServiceException e) {
/*  681 */       return null;
/*      */     }
/*  683 */     return remoteCalendarItem;
/*      */   }
/*      */   
/*      */ 
/*      */   private class ProcessInvitesStatus
/*      */   {
/*  689 */     boolean updatedMetadata = false;
/*  690 */     int calItemFolderId = 10;
/*      */     
/*      */ 
/*  693 */     boolean isForwardedInvite = false;
/*  694 */     String intendedForAddress = null;
/*  695 */     boolean intendedForMe = true;
/*  696 */     boolean intendedForCalendarIManage = false;
/*  697 */     boolean addRevision = false;
/*      */     
/*      */     boolean autoAddNew;
/*      */     
/*  701 */     AccountUtil.AccountAddressMatcher acctMatcher = null;
/*      */     private final Account account;
/*  703 */     CalendarItem calItem = null;
/*      */     
/*      */     ProcessInvitesStatus(Account acct, ParsedMessage pm) throws ServiceException {
/*  706 */       this.account = acct;
/*  707 */       String headerVal = Message.getCalendarIntendedFor(pm.getMimeMessage());
/*  708 */       if ((headerVal != null) && (headerVal.length() > 0)) {
/*  709 */         this.isForwardedInvite = true;
/*  710 */         this.intendedForAddress = headerVal;
/*  711 */         this.intendedForMe = getAcctMatcher().matches(headerVal);
/*  712 */         if (!this.intendedForMe) {
/*  713 */           Message.this.calendarIntendedFor = headerVal;
/*  714 */           this.intendedForCalendarIManage = Message.this.manageCalendar(Message.this.calendarIntendedFor);
/*      */         }
/*      */       }
/*      */     }
/*      */     
/*      */     void initAddRevisionSetting(String uid, Set<String> calUidsSeen) {
/*  720 */       if (!calUidsSeen.contains(uid)) {
/*  721 */         this.addRevision = true;
/*  722 */         calUidsSeen.add(uid);
/*      */       } else {
/*  724 */         this.addRevision = false;
/*      */       }
/*      */     }
/*      */     
/*      */     void initAutoAddNew(OperationContext octxt) {
/*  729 */       if ((octxt != null) && ((octxt.getPlayer() instanceof CreateCalendarItemPlayer)))
/*      */       {
/*      */ 
/*  732 */         CreateCalendarItemPlayer player = (CreateCalendarItemPlayer)octxt.getPlayer();
/*  733 */         this.autoAddNew = (player.getCalendarItemId() != 0);
/*      */       } else {
/*  735 */         this.autoAddNew = this.account.isPrefCalendarAutoAddInvites();
/*      */       }
/*      */     }
/*      */     
/*      */     AccountUtil.AccountAddressMatcher getAcctMatcher() throws ServiceException
/*      */     {
/*  741 */       if (this.acctMatcher == null) {
/*  742 */         this.acctMatcher = new AccountUtil.AccountAddressMatcher(this.account);
/*      */       }
/*  744 */       return this.acctMatcher;
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   private void processInvitesAfterCreate(String method, int folderId, boolean applyToCalendar, ParsedMessage pm, List<Invite> invites)
/*      */     throws ServiceException
/*      */   {
/*  755 */     if (pm == null) {
/*  756 */       throw ServiceException.INVALID_REQUEST("null ParsedMessage while processing invite in message " + this.mId, null);
/*      */     }
/*      */     
/*  759 */     Account acct = getAccount();
/*  760 */     AccountUtil.AccountAddressMatcher acctMatcher = new AccountUtil.AccountAddressMatcher(acct);
/*  761 */     OperationContext octxt = getMailbox().getOperationContext();
/*      */     
/*  763 */     ProcessInvitesStatus status = new ProcessInvitesStatus(acct, pm);
/*  764 */     status.initAutoAddNew(octxt);
/*      */     
/*  766 */     boolean isOrganizerMethod = Invite.isOrganizerMethod(method);
/*  767 */     if ((isOrganizerMethod) && (!invites.isEmpty()) && (status.intendedForMe))
/*      */     {
/*      */ 
/*      */ 
/*      */ 
/*  772 */       Account senderAcct = null;
/*  773 */       boolean onBehalfOf = false;
/*      */       
/*  775 */       AccessManager accessMgr = AccessManager.getInstance();
/*  776 */       boolean canInvite; String senderEmail; boolean canInvite; if ((octxt != null) && (octxt.getAuthenticatedUser() != null)) {
/*  777 */         onBehalfOf = octxt.isDelegatedRequest(getMailbox());
/*  778 */         senderAcct = octxt.getAuthenticatedUser();
/*  779 */         String senderEmail = senderAcct.getName();
/*  780 */         canInvite = accessMgr.canDo(senderAcct, acct, Rights.User.R_invite, octxt.isUsingAdminPrivileges());
/*      */       } else {
/*  782 */         senderEmail = pm.getSenderEmail(false);
/*  783 */         if (senderEmail != null) {
/*  784 */           senderAcct = Provisioning.getInstance().get(Key.AccountBy.name, senderEmail);
/*      */         }
/*  786 */         canInvite = accessMgr.canDo(senderEmail, acct, Rights.User.R_invite, false);
/*      */       }
/*  788 */       if (!canInvite) {
/*  789 */         Invite invite = (Invite)invites.get(0);
/*  790 */         CalendarMailSender.handleInviteAutoDeclinedNotification(octxt, getMailbox(), acct, senderEmail, senderAcct, onBehalfOf, applyToCalendar, getId(), invite);
/*      */         
/*  792 */         String inviteSender = senderEmail != null ? senderEmail : "unknown sender";
/*  793 */         ZimbraLog.calendar.info("Calendar invite from %s to %s is not allowed", new Object[] { inviteSender, acct.getName() });
/*      */         
/*      */ 
/*      */ 
/*  797 */         status.autoAddNew = false;
/*      */       }
/*      */     }
/*      */     
/*      */ 
/*  802 */     ZAttrProvisioning.PrefCalendarApptVisibility prefClass = acct.getPrefCalendarApptVisibility();
/*  803 */     boolean forcePrivateClass = (prefClass != null) && (!prefClass.equals(ZAttrProvisioning.PrefCalendarApptVisibility.public_));
/*      */     
/*      */ 
/*  806 */     boolean allowOrganizerAlarm = DebugConfig.calendarAllowOrganizerSpecifiedAlarms;
/*      */     
/*  808 */     if (this.calendarItemInfos == null) {
/*  809 */       this.calendarItemInfos = new ArrayList();
/*      */     }
/*      */     
/*      */     ZOrganizer seriesOrganizer;
/*      */     
/*      */     boolean seriesIsOrganizer;
/*      */     List<ZAttendee> seriesAttendees;
/*      */     ParsedDateTime seriesDtStart;
/*  817 */     if (invites.size() > 1) {
/*  818 */       boolean hasSeries = false;
/*  819 */       seriesOrganizer = null;
/*  820 */       seriesIsOrganizer = false;
/*  821 */       seriesAttendees = null;
/*  822 */       seriesDtStart = null;
/*      */       
/*  824 */       for (Invite inv : invites) {
/*  825 */         if (!inv.hasRecurId()) {
/*  826 */           hasSeries = true;
/*  827 */           seriesOrganizer = inv.getOrganizer();
/*  828 */           seriesIsOrganizer = inv.isOrganizer();
/*  829 */           seriesAttendees = inv.getAttendees();
/*  830 */           seriesDtStart = inv.getStartTime();
/*  831 */           break;
/*      */         }
/*      */       }
/*  834 */       if (hasSeries) {
/*  835 */         for (Invite inv : invites) {
/*  836 */           RecurId rid = inv.getRecurId();
/*  837 */           if (rid != null) {
/*  838 */             if ((seriesOrganizer != null) && (!inv.hasOrganizer())) {
/*  839 */               inv.setOrganizer(seriesOrganizer);
/*  840 */               inv.setIsOrganizer(seriesIsOrganizer);
/*      */               
/*      */ 
/*      */ 
/*  844 */               if ((!inv.hasOtherAttendees()) && (seriesAttendees != null)) {
/*  845 */                 for (ZAttendee at : seriesAttendees) {
/*  846 */                   inv.addAttendee(at);
/*      */                 }
/*      */               }
/*      */             }
/*  850 */             if ((!inv.isAllDayEvent()) && (seriesDtStart != null))
/*      */             {
/*      */ 
/*  853 */               ParsedDateTime ridDt = rid.getDt();
/*  854 */               if ((ridDt != null) && (ridDt.hasZeroTime()) && (!seriesDtStart.hasZeroTime()) && (ridDt.sameTimeZone(seriesDtStart)))
/*      */               {
/*  856 */                 ParsedDateTime fixedDt = seriesDtStart.cloneWithNewDate(ridDt);
/*  857 */                 RecurId fixedRid = new RecurId(fixedDt, rid.getRange());
/*  858 */                 ZimbraLog.calendar.debug("Fixed up invalid RECURRENCE-ID with zero time; before=[%s], after=[%s]", new Object[] { rid, fixedRid });
/*      */                 
/*  860 */                 inv.setRecurId(fixedRid);
/*      */               }
/*      */             }
/*      */             
/*      */ 
/*      */ 
/*  866 */             inv.setMailItemId(0);
/*      */           }
/*      */         }
/*      */       }
/*      */     }
/*      */     
/*  872 */     boolean publicInvites = true;
/*  873 */     status.calItemFolderId = ((invites.size() > 0) && (((Invite)invites.get(0)).isTodo()) ? 15 : 10);
/*  874 */     CalendarItem firstCalItem = null;
/*  875 */     Set<String> calUidsSeen = new HashSet();
/*  876 */     for (Invite cur : invites) {
/*  877 */       if (!cur.isPublic()) {
/*  878 */         publicInvites = false;
/*      */       }
/*      */       
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*  885 */       if ((!cur.hasOrganizer()) && (cur.hasOtherAttendees())) {
/*  886 */         String fromEmail = pm.getSenderEmail(true);
/*  887 */         if (fromEmail != null) {
/*  888 */           boolean dangerousSender = false;
/*      */           
/*  890 */           if (status.intendedForAddress != null) {
/*  891 */             if (status.intendedForAddress.equalsIgnoreCase(fromEmail)) {
/*  892 */               ZimbraLog.calendar.info("Got malformed invite without organizer.  Clearing attendees to prevent inadvertent cancels.");
/*      */               
/*  894 */               cur.clearAttendees();
/*  895 */               dangerousSender = true;
/*      */             }
/*  897 */           } else if (acctMatcher.matches(fromEmail)) {
/*  898 */             ZimbraLog.calendar.info("Got malformed invite without organizer.  Clearing attendees to prevent inadvertent cancels.");
/*      */             
/*  900 */             cur.clearAttendees();
/*  901 */             dangerousSender = true;
/*      */           }
/*  903 */           if (!dangerousSender) {
/*  904 */             if ((isOrganizerMethod = Invite.isOrganizerMethod(method)))
/*      */             {
/*  906 */               ZOrganizer org = new ZOrganizer(fromEmail, null);
/*  907 */               String senderEmail = pm.getSenderEmail(false);
/*  908 */               if ((senderEmail != null) && (!senderEmail.equalsIgnoreCase(fromEmail)))
/*  909 */                 org.setSentBy(senderEmail);
/*  910 */               cur.setOrganizer(org);
/*  911 */               ZimbraLog.calendar.info("Got malformed invite that lists attendees without specifying an organizer.  Defaulting organizer to: " + org.toString());
/*      */ 
/*      */             }
/*      */             else
/*      */             {
/*      */ 
/*  917 */               ZOrganizer org = null;
/*  918 */               CalendarItem ci = this.mMailbox.getCalendarItemByUid(octxt, cur.getUid());
/*  919 */               if (ci != null) {
/*  920 */                 Invite inv = ci.getInvite(cur.getRecurId());
/*  921 */                 if (inv == null) {
/*  922 */                   inv = ci.getDefaultInviteOrNull();
/*      */                 }
/*  924 */                 if (inv != null) {
/*  925 */                   org = inv.getOrganizer();
/*      */                 }
/*      */               }
/*  928 */               if (org == null) {
/*  929 */                 if (status.intendedForAddress != null) {
/*  930 */                   org = new ZOrganizer(status.intendedForAddress, null);
/*      */                 } else {
/*  932 */                   org = new ZOrganizer(acct.getName(), null);
/*      */                 }
/*      */               }
/*  935 */               cur.setOrganizer(org);
/*  936 */               cur.setIsOrganizer(status.intendedForMe);
/*  937 */               ZimbraLog.calendar.info("Got malformed reply missing organizer.  Defaulting to " + org.toString());
/*      */             }
/*      */           }
/*      */         }
/*      */       }
/*      */       
/*  943 */       cur.setLocalOnly(false);
/*  944 */       status.initAddRevisionSetting(cur.getUid(), calUidsSeen);
/*      */       
/*      */ 
/*      */ 
/*  948 */       if ((cur.isEvent()) && ((acct instanceof CalendarResource))) {
/*  949 */         cur.setFreeBusy("B");
/*  950 */         cur.setTransparency("O");
/*      */       }
/*      */       
/*  953 */       if (forcePrivateClass) {
/*  954 */         cur.setClassProp("PRI");
/*  955 */         cur.setClassPropSetByMe(true);
/*      */       }
/*      */       
/*  958 */       ZCalendar.ICalTok methodTok = Invite.lookupMethod(method);
/*      */       
/*      */ 
/*  961 */       if (!allowOrganizerAlarm)
/*      */       {
/*  963 */         if ((cur.isEvent()) && (isOrganizerMethod) && (!cur.isCancel()) && (!ZCalendar.ICalTok.DECLINECOUNTER.equals(methodTok))) {
/*  964 */           Invite.setDefaultAlarm(cur, acct);
/*      */         }
/*      */       }
/*  967 */       getInfoForAssociatedCalendarItem(acct, cur, method, pm, applyToCalendar, status);
/*  968 */       if (firstCalItem == null) {
/*  969 */         firstCalItem = status.calItem;
/*      */       }
/*      */     }
/*      */     
/*  973 */     if (status.updatedMetadata) {
/*  974 */       saveMetadata();
/*      */     }
/*      */     
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*  984 */     if ((applyToCalendar) && (!status.isForwardedInvite) && (status.intendedForMe) && (folderId != 5) && (!invites.isEmpty()) && (!acct.isIsSystemResource()))
/*      */     {
/*      */ 
/*  987 */       RedoableOp redoPlayer = octxt != null ? octxt.getPlayer() : null;
/*  988 */       RedoLogProvider redoProvider = RedoLogProvider.getInstance();
/*  989 */       boolean needToForward = (redoProvider.isMaster()) && ((redoPlayer == null) || (redoProvider.getRedoLogManager().getInCrashRecovery()));
/*      */       
/*      */ 
/*  992 */       if (needToForward) {
/*  993 */         String[] forwardTo = null;
/*      */         
/*  995 */         if (isOrganizerMethod) {
/*  996 */           forwardTo = acct.getPrefCalendarForwardInvitesTo();
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */         }
/* 1002 */         else if (firstCalItem != null) {
/* 1003 */           Invite invCalItem = firstCalItem.getInvite(((Invite)invites.get(0)).getRecurId());
/* 1004 */           if (invCalItem == null)
/* 1005 */             invCalItem = firstCalItem.getDefaultInviteOrNull();
/* 1006 */           if ((invCalItem != null) && (invCalItem.isOrganizer())) {
/* 1007 */             ZOrganizer org = invCalItem.getOrganizer();
/* 1008 */             if (org.hasSentBy()) {
/* 1009 */               forwardTo = new String[] { org.getSentBy() };
/*      */             }
/*      */           }
/*      */         }
/*      */         
/*      */ 
/* 1015 */         Account senderAcct = null;
/* 1016 */         String senderEmail = pm.getSenderEmail(false);
/* 1017 */         if (senderEmail != null) {
/* 1018 */           senderAcct = Provisioning.getInstance().get(Key.AccountBy.name, senderEmail);
/*      */         }
/* 1020 */         if ((forwardTo != null) && (forwardTo.length > 0)) {
/* 1021 */           List<String> rcptsUnfiltered = new ArrayList();
/* 1022 */           List<String> rcptsFiltered = new ArrayList();
/* 1023 */           Folder calFolder = null;
/*      */           try {
/* 1025 */             calFolder = getMailbox().getFolderById(status.calItemFolderId);
/*      */           } catch (MailServiceException.NoSuchItemException e) {
/* 1027 */             ZimbraLog.mailbox.warn("No such calendar folder (" + status.calItemFolderId + ") during invite auto-forwarding");
/*      */           }
/* 1029 */           for (String fwd : forwardTo) {
/* 1030 */             if (fwd != null) {
/* 1031 */               fwd = fwd.trim();
/*      */             }
/* 1033 */             if (!StringUtil.isNullOrEmpty(fwd))
/*      */             {
/*      */ 
/*      */ 
/* 1037 */               if (!acctMatcher.matches(fwd))
/*      */               {
/*      */ 
/* 1040 */                 Account rcptAcct = Provisioning.getInstance().get(Key.AccountBy.name, fwd);
/* 1041 */                 boolean rcptIsSender = false;
/* 1042 */                 if (rcptAcct != null) {
/* 1043 */                   if (senderAcct != null) {
/* 1044 */                     rcptIsSender = rcptAcct.getId().equalsIgnoreCase(senderAcct.getId());
/*      */                   } else {
/* 1046 */                     rcptIsSender = AccountUtil.addressMatchesAccount(rcptAcct, senderEmail);
/*      */                   }
/*      */                 }
/* 1049 */                 else if (senderAcct != null) {
/* 1050 */                   rcptIsSender = AccountUtil.addressMatchesAccount(senderAcct, fwd);
/*      */                 } else {
/* 1052 */                   rcptIsSender = fwd.equalsIgnoreCase(senderEmail);
/*      */                 }
/*      */                 
/* 1055 */                 if (rcptIsSender) {
/* 1056 */                   ZimbraLog.calendar.info("Not auto-forwarding to " + fwd + " because it is the sender of this message");
/*      */ 
/*      */                 }
/* 1059 */                 else if (publicInvites) {
/* 1060 */                   rcptsUnfiltered.add(fwd);
/*      */                 } else {
/* 1062 */                   boolean allowed = false;
/* 1063 */                   if ((calFolder != null) && (rcptAcct != null)) {
/* 1064 */                     allowed = calFolder.canAccess((short)1024, rcptAcct, false);
/*      */                   }
/* 1066 */                   if (allowed) {
/* 1067 */                     rcptsUnfiltered.add(fwd);
/* 1068 */                   } else if ((acct instanceof CalendarResource))
/*      */                   {
/*      */ 
/*      */ 
/* 1072 */                     rcptsFiltered.add(fwd); }
/*      */                 }
/*      */               } }
/*      */           }
/* 1076 */           if ((!rcptsUnfiltered.isEmpty()) || (!rcptsFiltered.isEmpty())) {
/* 1077 */             MimeMessage mmOrig = pm.getMimeMessage();
/* 1078 */             if (mmOrig != null) {
/* 1079 */               String origSender = pm.getSenderEmail(false);
/* 1080 */               String forwarder = AccountUtil.getCanonicalAddress(acct);
/* 1081 */               if (!rcptsUnfiltered.isEmpty()) {
/* 1082 */                 MimeMessage mm = CalendarMailSender.createForwardedInviteMessage(mmOrig, origSender, forwarder, (String[])rcptsUnfiltered.toArray(new String[0]));
/*      */                 
/* 1084 */                 if (mm != null) {
/* 1085 */                   ItemId origMsgId = new ItemId(getMailbox(), getId());
/* 1086 */                   CalendarMailSender.sendInviteAutoForwardMessage(octxt, getMailbox(), origMsgId, mm);
/*      */                 }
/*      */               }
/* 1089 */               if (!rcptsFiltered.isEmpty()) {
/* 1090 */                 MimeMessage mm = CalendarMailSender.createForwardedPrivateInviteMessage(acct, acct.getLocale(), method, invites, origSender, forwarder, (String[])rcptsFiltered.toArray(new String[0]));
/*      */                 
/* 1092 */                 if (mm != null) {
/* 1093 */                   ItemId origMsgId = new ItemId(getMailbox(), getId());
/* 1094 */                   CalendarMailSender.sendInviteAutoForwardMessage(octxt, getMailbox(), origMsgId, mm);
/*      */                 }
/*      */               }
/*      */             }
/*      */           }
/*      */         }
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */   private void getInfoForAssociatedCalendarItem(Account acct, Invite cur, String method, ParsedMessage pm, boolean applyToCalendar, ProcessInvitesStatus status)
/*      */     throws ServiceException
/*      */   {
/* 1109 */     boolean calItemIsNew = false;
/* 1110 */     boolean modifiedCalItem = false;
/* 1111 */     boolean success = false;
/*      */     try {
/* 1113 */       InviteChanges invChanges = null;
/*      */       
/* 1115 */       ZCalendar.ZProperty changesProp = cur.getXProperty(ZCalendar.ICalTok.X_ZIMBRA_CHANGES.toString());
/* 1116 */       if (changesProp != null) {
/* 1117 */         invChanges = new InviteChanges(changesProp.getValue());
/*      */         
/*      */ 
/* 1120 */         cur.removeXProp(ZCalendar.ICalTok.X_ZIMBRA_CHANGES.toString());
/*      */       }
/* 1122 */       if ((!status.intendedForMe) && (!status.intendedForCalendarIManage))
/*      */       {
/* 1124 */         CalendarItemInfo info = new CalendarItemInfo(0, cur.getComponentNum(), cur, invChanges);
/*      */         
/* 1126 */         this.calendarItemInfos.add(info);
/* 1127 */         status.updatedMetadata = true;
/* 1128 */         success = true;
/*      */       }
/*      */       else
/*      */       {
/* 1132 */         OperationContext octxt = getMailbox().getOperationContext();
/* 1133 */         ZCalendar.ICalTok methodTok = Invite.lookupMethod(method);
/* 1134 */         AccountUtil.AccountAddressMatcher acctMatcher = status.getAcctMatcher();
/* 1135 */         cur.sanitize(true);
/* 1136 */         if (status.intendedForCalendarIManage) {
/* 1137 */           Provisioning prov = Provisioning.getInstance();
/* 1138 */           Account ownerAcct = prov.get(Key.AccountBy.name, this.calendarIntendedFor);
/* 1139 */           CalendarItemInfo cii = getMailbox().getRemoteCalItemByUID(ownerAcct, cur.getUid(), false, false);
/*      */           
/*      */ 
/* 1142 */           if (cii == null) {
/* 1143 */             CalendarItemInfo info = new CalendarItemInfo(0, cur.getComponentNum(), cur, invChanges);
/* 1144 */             this.calendarItemInfos.add(info);
/*      */           } else {
/*      */             int calItemId;
/*      */             String owner;
/*      */             try {
/* 1149 */               ItemId iid = new ItemId(cii.getId(), (String)null);
/* 1150 */               calItemId = iid.getId();
/* 1151 */               owner = iid.getAccountId();
/*      */             } catch (Exception e) {
/* 1153 */               calItemId = 0;
/* 1154 */               owner = null;
/*      */             }
/* 1156 */             CalendarItemInfo info = new CalendarItemInfo(calItemId, owner, cur.getComponentNum(), cur, invChanges);
/* 1157 */             this.calendarItemInfos.add(info);
/*      */           }
/* 1159 */           status.updatedMetadata = true;
/* 1160 */           success = true;
/*      */         }
/*      */         else {
/* 1163 */           status.calItem = this.mMailbox.getCalendarItemByUid(octxt, cur.getUid());
/* 1164 */           if ((applyToCalendar) && (!ZCalendar.ICalTok.REPLY.equals(methodTok)) && (!ZCalendar.ICalTok.COUNTER.equals(methodTok)) && (!ZCalendar.ICalTok.DECLINECOUNTER.equals(methodTok)))
/*      */           {
/*      */ 
/* 1167 */             if (status.calItem == null)
/*      */             {
/*      */ 
/* 1170 */               if ((ZCalendar.ICalTok.REQUEST.equals(methodTok)) || ((ZCalendar.ICalTok.PUBLISH.equals(methodTok)) && (getAccount().getBooleanAttr("zimbraPrefCalendarAllowPublishMethodInvite", false))))
/*      */               {
/*      */ 
/* 1173 */                 if (status.autoAddNew) {
/* 1174 */                   int flags = 0;
/*      */                   
/*      */ 
/* 1177 */                   int defaultFolder = cur.isTodo() ? 15 : 10;
/* 1178 */                   status.calItem = this.mMailbox.createCalendarItem(defaultFolder, flags, null, cur.getUid(), pm, cur, null);
/*      */                   
/* 1180 */                   calItemIsNew = true;
/* 1181 */                   status.calItemFolderId = status.calItem.getFolderId();
/*      */                 }
/*      */               } else {
/* 1184 */                 LOG.info("Mailbox %d Message %d SKIPPING Invite %s b/c no CalendarItem could be found", new Object[] { Integer.valueOf(getMailboxId()), Integer.valueOf(getId()), method });
/*      */ 
/*      */ 
/*      */               }
/*      */               
/*      */ 
/*      */ 
/*      */ 
/*      */             }
/*      */             else
/*      */             {
/*      */ 
/*      */ 
/* 1197 */               boolean ignore = false;
/* 1198 */               Invite defInv = status.calItem.getDefaultInviteOrNull();
/* 1199 */               if ((defInv != null) && (defInv.isOrganizer())) {
/* 1200 */                 ZOrganizer org = cur.getOrganizer();
/* 1201 */                 String orgAddress = org != null ? org.getAddress() : null;
/* 1202 */                 if (acctMatcher.matches(orgAddress)) {
/* 1203 */                   ignore = !acct.getBooleanAttr("zimbraPrefCalendarAllowCancelEmailToSelf", false);
/*      */                 }
/*      */               }
/* 1206 */               if (ignore) {
/* 1207 */                 ZimbraLog.calendar.info("Ignoring calendar request emailed from organizer to self, possibly in a mail loop involving mailing lists and/or forwards; calItemId=" + status.calItem.getId() + ", msgId=" + getId());
/*      */ 
/*      */ 
/*      */               }
/*      */               else
/*      */               {
/*      */ 
/* 1214 */                 if (status.addRevision) {
/* 1215 */                   status.calItem.snapshotRevision(false);
/*      */                 }
/*      */                 
/* 1218 */                 boolean discardExistingInvites = false;
/* 1219 */                 int calFolderId = status.calItem.getFolderId();
/* 1220 */                 if ((!cur.isCancel()) && (status.calItem.inTrash())) {
/* 1221 */                   discardExistingInvites = true;
/* 1222 */                   if (status.calItem.getType() == MailItem.Type.TASK) {
/* 1223 */                     calFolderId = 15;
/*      */                   } else {
/* 1225 */                     calFolderId = 10;
/*      */                   }
/*      */                 }
/*      */                 
/*      */ 
/*      */ 
/* 1231 */                 if ((invChanges == null) && (!cur.isCancel())) {
/* 1232 */                   Invite prev = status.calItem.getInvite(cur.getRecurId());
/* 1233 */                   if (prev == null)
/*      */                   {
/*      */ 
/* 1236 */                     Invite series = status.calItem.getInvite(null);
/* 1237 */                     if (series != null)
/* 1238 */                       prev = series.makeInstanceInvite(cur.getRecurId().getDt());
/*      */                   }
/* 1240 */                   if (prev != null) {
/* 1241 */                     invChanges = new InviteChanges(prev, cur);
/*      */                   }
/*      */                 }
/* 1244 */                 modifiedCalItem = status.calItem.processNewInvite(pm, cur, calFolderId, discardExistingInvites);
/* 1245 */                 status.calItemFolderId = calFolderId;
/* 1246 */                 status.calItem.getFolder().updateHighestMODSEQ();
/*      */               }
/*      */             }
/*      */           }
/*      */           
/* 1251 */           int calItemId = status.calItem != null ? status.calItem.getId() : 0;
/* 1252 */           CalendarItemInfo info = new CalendarItemInfo(calItemId, cur.getComponentNum(), cur, invChanges);
/* 1253 */           this.calendarItemInfos.add(info);
/* 1254 */           status.updatedMetadata = true;
/* 1255 */           if ((status.calItem != null) && ((calItemIsNew) || (modifiedCalItem))) {
/* 1256 */             this.mMailbox.index.add(status.calItem);
/*      */           }
/* 1258 */           success = true;
/*      */         }
/* 1260 */       } } finally { if ((!success) && (status.calItem != null))
/*      */       {
/*      */ 
/* 1263 */         getMailbox().uncache(status.calItem);
/*      */       }
/*      */     }
/*      */   }
/*      */   
/*      */   void updateBlobData(MailboxBlob mblob) throws IOException, ServiceException {
/* 1269 */     long size = mblob.getSize();
/* 1270 */     if ((getSize() == size) && (StringUtil.equal(getDigest(), mblob.getDigest())) && (StringUtil.equal(getLocator(), mblob.getLocator()))) {
/* 1271 */       return;
/*      */     }
/* 1273 */     this.mMailbox.updateSize(size - this.mData.size, true);
/* 1274 */     getFolder().updateSize(0, 0, size - this.mData.size);
/*      */     
/* 1276 */     this.mData.size = size;
/* 1277 */     this.mData.locator = mblob.getLocator();
/* 1278 */     this.mData.setBlobDigest(mblob.getDigest());
/* 1279 */     DbMailItem.saveBlobInfo(this);
/*      */   }
/*      */   
/*      */   void setCustomData(MailItem.CustomMetadata custom) throws ServiceException
/*      */   {
/* 1284 */     super.setCustomData(custom);
/*      */     
/* 1286 */     ((Conversation)getParent()).inheritedCustomDataChanged(this, custom);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   protected void updateUnread(int delta, int deletedDelta)
/*      */     throws ServiceException
/*      */   {
/* 1297 */     if (((delta == 0) && (deletedDelta == 0)) || (!trackUnread())) {
/* 1298 */       return;
/*      */     }
/* 1300 */     markItemModified(1);
/*      */     
/*      */ 
/* 1303 */     MailItem parent = getParent();
/*      */     
/*      */ 
/* 1306 */     this.mData.unreadCount += delta;
/* 1307 */     if (this.mData.unreadCount < 0) {
/* 1308 */       throw ServiceException.FAILURE("inconsistent state: unread < 0 for " + getClass().getName() + " " + this.mId, null);
/*      */     }
/*      */     
/*      */ 
/* 1312 */     getFolder().updateUnread(delta, deletedDelta);
/*      */     
/*      */ 
/* 1315 */     if (parent != null) {
/* 1316 */       parent.updateUnread(delta, deletedDelta);
/*      */     }
/*      */     
/*      */ 
/* 1320 */     updateTagUnread(delta, deletedDelta);
/*      */   }
/*      */   
/*      */   MailItem copy(Folder folder, int id, String uuid, MailItem newParent)
/*      */     throws IOException, ServiceException
/*      */   {
/* 1326 */     Message copy = (Message)super.copy(folder, id, uuid, newParent);
/*      */     
/* 1328 */     if (isDraft()) {
/* 1329 */       copy.setDraftAutoSendTime(0L);
/*      */     }
/*      */     
/* 1332 */     Conversation parent = (Conversation)getParent();
/* 1333 */     if ((parent instanceof VirtualConversation)) if (parent.getId() == (newParent == null ? -1 : newParent.mId)) if ((!isDraft()) && (inSpam() == folder.inSpam()))
/*      */         {
/*      */ 
/* 1336 */           Conversation conv = this.mMailbox.createConversation(-1, new Message[] { this, copy });
/* 1337 */           DbMailItem.changeOpenTargets(this, conv.getId());
/* 1338 */           parent.removeChild(this);
/*      */         }
/* 1340 */     return copy;
/*      */   }
/*      */   
/*      */ 
/*      */   MailItem icopy(Folder target, int copyId, String copyUuid)
/*      */     throws IOException, ServiceException
/*      */   {
/* 1347 */     Message copy = (Message)super.icopy(target, copyId, copyUuid);
/* 1348 */     if (isDraft()) {
/* 1349 */       copy.setDraftAutoSendTime(0L);
/*      */     }
/* 1351 */     return copy;
/*      */   }
/*      */   
/*      */ 
/*      */   boolean move(Folder target)
/*      */     throws ServiceException
/*      */   {
/* 1358 */     boolean moved = super.move(target);
/* 1359 */     if ((moved) && (isDraft()) && (target.inTrash())) {
/* 1360 */       setDraftAutoSendTime(0L);
/*      */     }
/* 1362 */     return moved;
/*      */   }
/*      */   
/*      */   public List<IndexDocument> generateIndexData() throws MailItem.TemporaryIndexingException
/*      */   {
/*      */     try {
/* 1368 */       ParsedMessage pm = null;
/* 1369 */       this.mMailbox.lock.lock();
/*      */       try
/*      */       {
/* 1372 */         ParsedMessageOptions opt = new ParsedMessageOptions().setContent(getMimeMessage(false)).setReceivedDate(getDate()).setAttachmentIndexing(getMailbox().attachmentsIndexingEnabled()).setSize(getSize()).setDigest(getDigest());
/*      */         
/*      */ 
/*      */ 
/*      */ 
/* 1377 */         pm = new ParsedMessage(opt);
/*      */       } finally {
/* 1379 */         this.mMailbox.lock.release();
/*      */       }
/*      */       
/* 1382 */       pm.setDefaultCharset(getAccount().getPrefMailDefaultCharset());
/*      */       
/* 1384 */       if (this.mMailbox.index.isReIndexInProgress()) {
/* 1385 */         getMailbox().reanalyze(getId(), getType(), pm, getSize());
/*      */       }
/*      */       
/*      */ 
/* 1389 */       pm.analyzeFully();
/*      */       
/* 1391 */       if (pm.hasTemporaryAnalysisFailure()) {
/* 1392 */         throw new MailItem.TemporaryIndexingException();
/*      */       }
/* 1394 */       return pm.getLuceneDocuments();
/*      */     } catch (ServiceException e) {
/* 1396 */       ZimbraLog.index.warn("Unable to generate index data for Message %d. Item will not be indexed.", Integer.valueOf(getId()), e); }
/* 1397 */     return Collections.emptyList();
/*      */   }
/*      */   
/*      */   void reanalyze(Object data, long newSize)
/*      */     throws ServiceException
/*      */   {
/* 1403 */     if (!(data instanceof ParsedMessage)) {
/* 1404 */       throw ServiceException.FAILURE("cannot reanalyze non-ParsedMessage object", null);
/*      */     }
/*      */     
/* 1407 */     Account acct = getAccount();
/* 1408 */     ParsedMessage pm = (ParsedMessage)data;
/* 1409 */     MailItem parent = getParent();
/*      */     
/*      */ 
/* 1412 */     if (!getSubject().equals(pm.getSubject())) {
/* 1413 */       markItemModified(64);
/*      */     }
/*      */     
/* 1416 */     this.rawSubject = pm.getSubject();
/* 1417 */     this.mData.setSubject(pm.getNormalizedSubject());
/*      */     
/* 1419 */     markItemModified(524288);
/*      */     
/*      */ 
/* 1422 */     this.recipients = pm.getRecipients();
/*      */     
/*      */ 
/* 1425 */     this.fragment = pm.getFragment(acct.getLocale());
/*      */     
/*      */ 
/* 1428 */     boolean hadAttachment = this.mData.isSet(Flag.FlagInfo.ATTACHED);
/* 1429 */     this.mData.unsetFlag(Flag.FlagInfo.ATTACHED);
/* 1430 */     if (pm.hasAttachments()) {
/* 1431 */       this.mData.setFlag(Flag.FlagInfo.ATTACHED);
/*      */     }
/* 1433 */     if (hadAttachment != pm.hasAttachments()) {
/* 1434 */       markItemModified(4);
/* 1435 */       parent.tagChanged(this.mMailbox.getFlagById(Flag.ID_ATTACHED), pm.hasAttachments());
/*      */     }
/*      */     
/*      */ 
/* 1439 */     int oldUrgency = this.mData.getFlags() & (Flag.BITMASK_HIGH_PRIORITY | Flag.BITMASK_LOW_PRIORITY);
/* 1440 */     int urgency = pm.getPriorityBitmask();
/* 1441 */     this.mData.unsetFlag(Flag.FlagInfo.HIGH_PRIORITY);
/* 1442 */     this.mData.unsetFlag(Flag.FlagInfo.LOW_PRIORITY);
/* 1443 */     this.mData.setFlags(this.mData.getFlags() | urgency);
/* 1444 */     if (oldUrgency != urgency) {
/* 1445 */       markItemModified(4);
/* 1446 */       if ((urgency == Flag.BITMASK_HIGH_PRIORITY) || (oldUrgency == Flag.BITMASK_HIGH_PRIORITY)) {
/* 1447 */         parent.tagChanged(this.mMailbox.getFlagById(Flag.ID_HIGH_PRIORITY), urgency == Flag.BITMASK_HIGH_PRIORITY);
/*      */       }
/* 1449 */       if ((urgency == Flag.BITMASK_LOW_PRIORITY) || (oldUrgency == Flag.BITMASK_LOW_PRIORITY)) {
/* 1450 */         parent.tagChanged(this.mMailbox.getFlagById(Flag.ID_LOW_PRIORITY), urgency == Flag.BITMASK_LOW_PRIORITY);
/*      */       }
/*      */     }
/*      */     
/*      */ 
/* 1455 */     if (this.mData.size != newSize) {
/* 1456 */       markItemModified(16);
/* 1457 */       this.mMailbox.updateSize(newSize - this.mData.size, false);
/* 1458 */       getFolder().updateSize(0, 0, newSize - this.mData.size);
/* 1459 */       this.mData.size = newSize;
/*      */     }
/*      */     
/*      */ 
/* 1463 */     saveData(new DbMailItem(this.mMailbox), encodeMetadata(this.mRGBColor, this.mMetaVersion, this.mVersion, this.mExtendedData, pm, this.fragment, this.draftInfo, this.calendarItemInfos, this.calendarIntendedFor));
/*      */     
/*      */ 
/* 1466 */     if ((parent instanceof VirtualConversation)) {
/* 1467 */       ((VirtualConversation)parent).recalculateMetadata(Collections.singletonList(this));
/*      */     }
/*      */   }
/*      */   
/*      */   void detach() throws ServiceException
/*      */   {
/* 1473 */     MailItem parent = getParent();
/* 1474 */     if (!(parent instanceof Conversation)) {
/* 1475 */       return;
/*      */     }
/*      */     
/* 1478 */     if (parent.getSize() <= 1L) {
/* 1479 */       this.mMailbox.closeConversation((Conversation)parent, null);
/*      */     }
/*      */     else {
/* 1482 */       markItemModified(512);
/* 1483 */       parent.removeChild(this);
/*      */       
/* 1485 */       VirtualConversation vconv = new VirtualConversation(this.mMailbox, this);
/* 1486 */       this.mData.parentId = vconv.getId();
/* 1487 */       DbMailItem.setParent(this, vconv);
/*      */     }
/*      */   }
/*      */   
/*      */   void delete(boolean writeTombstones) throws ServiceException
/*      */   {
/* 1493 */     MailItem parent = getParent();
/* 1494 */     if (((parent instanceof Conversation)) && (((Conversation)parent).getMessageCount() == 1)) {
/* 1495 */       parent.delete(writeTombstones);
/*      */     } else {
/* 1497 */       super.delete(writeTombstones);
/*      */     }
/*      */   }
/*      */   
/*      */   void decodeMetadata(Metadata meta) throws ServiceException
/*      */   {
/* 1503 */     super.decodeMetadata(meta);
/*      */     
/* 1505 */     this.sender = meta.get("s", null);
/* 1506 */     this.recipients = meta.get("t", null);
/* 1507 */     this.fragment = meta.get("f", null);
/*      */     
/* 1509 */     if (meta.containsKey("ais")) {
/* 1510 */       this.calendarItemInfos = new ArrayList();
/* 1511 */       MetadataList mdList = meta.getList("ais");
/* 1512 */       for (int i = 0; i < mdList.size(); i++) {
/* 1513 */         Metadata md = mdList.getMap(i);
/* 1514 */         this.calendarItemInfos.add(CalendarItemInfo.decodeMetadata(md, getMailbox()));
/*      */       }
/*      */     }
/* 1517 */     this.calendarIntendedFor = meta.get("cif", null);
/*      */     
/* 1519 */     Metadata draftMeta = meta.getMap("d", true);
/* 1520 */     if (draftMeta != null) {
/* 1521 */       this.draftInfo = new DraftInfo(draftMeta);
/*      */     }
/*      */     
/* 1524 */     String prefix = meta.get("p", null);
/* 1525 */     if (prefix != null) {
/* 1526 */       this.rawSubject = (prefix + this.mData.getSubject());
/*      */     } else {
/* 1528 */       this.rawSubject = this.mData.getSubject();
/*      */     }
/* 1530 */     String rawSubj = meta.get("r", null);
/* 1531 */     if (rawSubj != null) {
/* 1532 */       this.rawSubject = rawSubj;
/*      */     }
/*      */   }
/*      */   
/*      */   Metadata encodeMetadata(Metadata meta)
/*      */   {
/* 1538 */     return encodeMetadata(meta, this.mRGBColor, this.mMetaVersion, this.mVersion, this.mExtendedData, this.sender, this.recipients, this.fragment, this.mData.getSubject(), this.rawSubject, this.draftInfo, this.calendarItemInfos, this.calendarIntendedFor);
/*      */   }
/*      */   
/*      */ 
/*      */   private static Metadata encodeMetadata(Color color, int metaVersion, int version, MailItem.CustomMetadata.CustomMetadataList extended, ParsedMessage pm, String fragment, DraftInfo dinfo, List<CalendarItemInfo> calItemInfos, String calIntendedFor)
/*      */   {
/* 1544 */     return encodeMetadata(new Metadata(), color, metaVersion, version, extended, pm.getSender(), pm.getRecipients(), fragment, pm.getNormalizedSubject(), pm.getSubject(), dinfo, calItemInfos, calIntendedFor);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   static Metadata encodeMetadata(Metadata meta, Color color, int metaVersion, int version, MailItem.CustomMetadata.CustomMetadataList extended, String sender, String recipients, String fragment, String subject, String rawSubj, DraftInfo dinfo, List<CalendarItemInfo> calItemInfos, String calIntendedFor)
/*      */   {
/* 1553 */     String prefix = null;
/* 1554 */     if ((rawSubj == null) || (rawSubj.equals(subject))) {
/* 1555 */       rawSubj = null;
/* 1556 */     } else if (rawSubj.endsWith(subject)) {
/* 1557 */       prefix = rawSubj.substring(0, rawSubj.length() - subject.length());
/* 1558 */       rawSubj = null;
/*      */     }
/*      */     
/* 1561 */     meta.put("s", sender);
/* 1562 */     meta.put("t", recipients);
/* 1563 */     meta.put("f", fragment);
/* 1564 */     meta.put("p", prefix);
/* 1565 */     meta.put("r", rawSubj);
/*      */     
/* 1567 */     if (calItemInfos != null) {
/* 1568 */       MetadataList mdList = new MetadataList();
/* 1569 */       for (CalendarItemInfo info : calItemInfos) {
/* 1570 */         mdList.add(info.encodeMetadata());
/*      */       }
/* 1572 */       meta.put("ais", mdList);
/*      */     }
/* 1574 */     meta.put("cif", calIntendedFor);
/*      */     
/* 1576 */     if (dinfo != null) {
/* 1577 */       Metadata dmeta = new Metadata();
/* 1578 */       dmeta.put("do", dinfo.origId);
/* 1579 */       dmeta.put("dt", dinfo.replyType);
/* 1580 */       dmeta.put("idnt", dinfo.identityId);
/* 1581 */       dmeta.put("aid", dinfo.accountId);
/* 1582 */       dmeta.put("ast", dinfo.autoSendTime);
/* 1583 */       meta.put("d", dmeta);
/*      */     }
/*      */     
/* 1586 */     return MailItem.encodeMetadata(meta, color, null, metaVersion, version, extended);
/*      */   }
/*      */   
/*      */ 
/*      */ 
/*      */ 
/*      */ 
/*      */   protected boolean isQuotaCheckRequired()
/*      */     throws ServiceException
/*      */   {
/* 1596 */     Account account = getMailbox().getAccount();
/* 1597 */     return !account.isMailAllowReceiveButNotSendWhenOverQuota();
/*      */   }
/*      */   
/*      */   public String toString()
/*      */   {
/* 1602 */     Objects.ToStringHelper helper = Objects.toStringHelper(this);
/* 1603 */     appendCommonMembers(helper);
/* 1604 */     helper.add("sender", this.sender);
/* 1605 */     if (this.recipients != null) {
/* 1606 */       helper.add("to", this.recipients);
/*      */     }
/* 1608 */     helper.add("fragment", this.fragment);
/* 1609 */     return helper.toString();
/*      */   }
/*      */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/mailbox/Message.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */